//=============================================================================
/**
 *
 *	@file		fld_arceus_eff.c
 *
 *	@brief		フィールドアルセウスエフェクト
 *	@author		NozomuSaito
 *	@data		2009.04.11
 *
 *	モジュール名：FldArceusEff_
 *
 */
//=============================================================================

#include "common.h"
#include "system/wipe.h"
#include "fieldsys.h"
#include "fieldobj.h"

#include "fld_demo.naix"

#include "fld_arceus_eff_def.h"

#include "fld_arceus_eff.h"

#define ANN_ANM_NUM		(2)		//アニメデータの数
#define ANN_SET_NUM		(2)		//アンノーンセット数
#define EFF_ANM_NUM	(2)		//光エフェクトアニメデータ数

#define FBALL_ANM_NUM	(4)		//発光体アニメ数

typedef struct
{
	FIELDSYS_WORK * fsys;
	NNSFndAllocator Allocator;
	FLD_3DOBJ_MDL	AnnMdl[ANN_SET_NUM];
	FLD_3DOBJ_ANM	AnnAnm[ANN_SET_NUM][ANN_ANM_NUM];
	FLD_3DOBJ		AnnObj[ANN_SET_NUM];

	FLD_3DOBJ_MDL	EffMdl;
	FLD_3DOBJ_ANM	EffAnm[EFF_ANM_NUM];
	FLD_3DOBJ		EffObj;

	u8 AnnAnmStart;
	u8 EffAnmStart;
	u8 DrawFlg;
	u8 Wait;

}FLD_ANNONE_WORK;

typedef struct
{
	FIELDSYS_WORK * fsys;
	NNSFndAllocator Allocator;
	FLD_3DOBJ_MDL	Mdl;
	FLD_3DOBJ_ANM	Anm[FBALL_ANM_NUM];
	FLD_3DOBJ		Obj;

	u8 AnmStart;
	u8 AnmEnd;
	u8 DrawFlg;
	u8 Type;		//	0:ディアルガ 1:パルキア 2:ギラティナ

}FLD_FBALL_WORK;


enum{
	ANN_SEQ_WHITE_OUT_FIRST,
	ANN_SEQ_EFF_LOAD,
	ANN_SEQ_WHITE_IN_WAIT,
	ANN_SEQ_LIGHT_EFF_START,
	ANN_SEQ_WHITE_OUT,
	ANN_SEQ_EFF_WAIT
};

enum{
	FB_SEQ_WHITE_OUT_FIRST,
	FB_SEQ_EFF_LOAD,
	FB_SEQ_WHITE_IN_WAIT,
	FB_SEQ_WAIT_ANM_END,
	FB_SEQ_END
};



static BOOL FldAnnoneEvt(GMEVENT_CONTROL * event);
static BOOL FldFlashBallEvt(GMEVENT_CONTROL * event);

static void LoadAnn3DData(FLD_ANNONE_WORK *work);
static void DelAnn3DData(FLD_ANNONE_WORK *work);
static void LoadFb3DData(FLD_FBALL_WORK *work);
static void DelFb3DData(FLD_FBALL_WORK *work);
static void SetAnmFrame(FLD_3DOBJ_ANM *anm, const u8 anm_num, const u32 inFrame);
static BOOL AnimeNoLoop(FLD_3DOBJ_ANM *anm, const u8 anm_num);

//--------------------------------------------------------------
/**
 * イベントコール関数
 * @param	fsys			フィールドシステムポインタ
 * @return	none
 */
//--------------------------------------------------------------
void FldArceusEff_CallAnnoneEvt(FIELDSYS_WORK * fsys)
{
	FLD_ANNONE_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(FLD_ANNONE_WORK));
	MI_CpuClear8(work, sizeof(FLD_ANNONE_WORK));
	work->fsys = fsys;
	//イベント発行
	FieldEvent_Call(fsys->event, FldAnnoneEvt, work);
}

//--------------------------------------------------------------
/**
 * イベント関数
 * @param	event	イベントポインタ
 * @return	BOOL	TRUEで終了
 */
//--------------------------------------------------------------
static BOOL FldAnnoneEvt(GMEVENT_CONTROL * event)
{
	int *seq = FieldEvent_GetSeqWork(event);
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	FLD_ANNONE_WORK* work = FieldEvent_GetSpecialWork(event);

	switch(*seq){
	case ANN_SEQ_WHITE_OUT_FIRST:
		WIPE_SYS_Start(	WIPE_PATTERN_M, WIPE_TYPE_FADEOUT,
						WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE, ANN_WHITE_OUT_FIRST_SYNC, 1, HEAPID_FIELD );
		(*seq)++;
		break;
	case ANN_SEQ_EFF_LOAD:
		//ホワイトアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			//データロード
			LoadAnn3DData(work);
			//ホワイトイン
			WIPE_SYS_Start(	WIPE_PATTERN_M, WIPE_TYPE_FADEIN,
						WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE, ANN_WHITE_IN_SYNC, 1, HEAPID_FIELD );
			(*seq)++;
		}
		break;
	case ANN_SEQ_WHITE_IN_WAIT:
		if( WIPE_SYS_EndCheck() ){
			//アニメ開始
			work->AnnAnmStart = 1;
			work->Wait = 0;
			//光エフェクト描画フラグ設定	(表示)
			FLD_3DObjSetDraw( &work->EffObj, TRUE );
			(*seq)++;
		}
		break;
	case ANN_SEQ_LIGHT_EFF_START:
		work->Wait++;
		if ( work->Wait >= ANN_WAIT_LIGHT_EFF_START ){
			//光アニメ開始
			work->EffAnmStart = 1;
			work->Wait = 0;
			(*seq)++;
		}
		break;
	case ANN_SEQ_WHITE_OUT:
		work->Wait++;
		if ( work->Wait >= ANN_WAIT_LAST_WHITE_OUT_START ){
			WIPE_SYS_Start(	WIPE_PATTERN_M, WIPE_TYPE_FADEOUT,
						WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE, ANN_WHITE_OUT_LAST_SYNC, 1, HEAPID_FIELD );
			(*seq)++;
		}
		break;
	case ANN_SEQ_EFF_WAIT:
		if ( WIPE_SYS_EndCheck() ){
			//解放処理
			{
				DelAnn3DData(work);
				sys_FreeMemoryEz(work);		//ワーク解放
			}
			return TRUE;
		}
	}

	//3Dアニメ
	if (work->AnnAnmStart){
		AnimeNoLoop(work->AnnAnm[0], ANN_ANM_NUM);
		AnimeNoLoop(work->AnnAnm[1], ANN_ANM_NUM);
	}
	if (work->EffAnmStart){
		AnimeNoLoop(work->EffAnm, EFF_ANM_NUM);
	};

	//3D描画
	if (work->DrawFlg){
		FLD_3DObjDraw( &work->AnnObj[0] );
		FLD_3DObjDraw( &work->AnnObj[1] );
		FLD_3DObjDraw( &work->EffObj );
	}
	return FALSE;
}

//--------------------------------------------------------------
/**
 * 3Ｄデータロード関数
 * @param	work	ワークポインタ
 * @return	none
 */
//--------------------------------------------------------------
static void LoadAnn3DData(FLD_ANNONE_WORK *work)
{
	u8 i,j;
	int heap = HEAPID_FIELD;
	const int anm[ANN_SET_NUM][ANN_ANM_NUM] = {
		{
			NARC_fld_demo_sin_an1_nsbca,
			NARC_fld_demo_sin_an1_nsbta,
		},
		{
			NARC_fld_demo_sin_an2_nsbca,
			NARC_fld_demo_sin_an2_nsbta,
		},
	};

	const int eff_anm[EFF_ANM_NUM] = {
		NARC_fld_demo_sin_hikari_nsbca,
		NARC_fld_demo_sin_hikari_nsbma,
	};

	const int mdl[ANN_SET_NUM] = {
		NARC_fld_demo_sin_an1_nsbmd,
		NARC_fld_demo_sin_an2_nsbmd,
	};

	// アロケーター作成
	sys_InitAllocator( &work->Allocator, heap, 32 );

	//モデルロード
	for (i=0;i<ANN_SET_NUM;i++){
		FLD_3DObjMdlLoad(&work->AnnMdl[i], ARC_FLD_DEMO_GRA , mdl[i], heap);
	}
	FLD_3DObjMdlLoad(&work->EffMdl, ARC_FLD_DEMO_GRA , NARC_fld_demo_sin_hikari_nsbmd, heap);

	//アニメデータロード
	for (j=0;j<ANN_SET_NUM;j++){
		for (i=0;i<ANN_ANM_NUM;i++){
			FLD_3DObjAnmLoad(	&work->AnnAnm[j][i], &work->AnnMdl[j], ARC_FLD_DEMO_GRA, anm[j][i],
								heap, &work->Allocator );
		}
	}
	for (i=0;i<EFF_ANM_NUM;i++){
		FLD_3DObjAnmLoad(	&work->EffAnm[i], &work->EffMdl, ARC_FLD_DEMO_GRA, eff_anm[i],
							heap, &work->Allocator );
	}

	//描画オブジェクト初期化
	for (i=0;i<ANN_SET_NUM;i++){
		FLD_3DObjInit( &work->AnnObj[i], &work->AnnMdl[i] );
	}
	FLD_3DObjInit( &work->EffObj, &work->EffMdl );

	//アニメをリンク
	for (j=0;j<ANN_SET_NUM;j++){
		for (i=0;i<ANN_ANM_NUM;i++){
			FLD_3DObjAddAnm( &work->AnnObj[j], &work->AnnAnm[j][i] );
		}
	}
	for (i=0;i<EFF_ANM_NUM;i++){
		FLD_3DObjAddAnm( &work->EffObj, &work->EffAnm[i] );
	}

	for (i=0;i<ANN_SET_NUM;i++){
		//描画フラグ設定	(表示)
		FLD_3DObjSetDraw( &work->AnnObj[i], TRUE );
		//フレームセット
		SetAnmFrame(work->AnnAnm[i], ANN_ANM_NUM, 0);
	}
	//光エフェクト描画フラグ設定	(非表示)
	FLD_3DObjSetDraw( &work->EffObj, FALSE );
	//フレームセット
	SetAnmFrame(work->EffAnm, EFF_ANM_NUM, 0);

	//表示位置セット
	{
		VecFx32 vec;
		//連れ歩き（アルセウス）の位置に表示
		FieldOBJ_VecPosGet( PairPoke_GetFldObjPtr(work->fsys), &vec );
		for (i=0;i<ANN_SET_NUM;i++){
			FLD_3DObjSetMatrix( &work->AnnObj[i], vec.x, vec.y, vec.z );
		}
		FLD_3DObjSetMatrix( &work->EffObj, vec.x, vec.y, vec.z );
	}

	//描画開始
	work->DrawFlg = 1;
}

//--------------------------------------------------------------
/**
 * 3Ｄデータ解放関数
 * @param	work	ワークポインタ
 * @return	none
 */
//--------------------------------------------------------------
static void DelAnn3DData(FLD_ANNONE_WORK *work)
{
	u8 i,j;
	for (j=0;j<ANN_SET_NUM;j++){
		//アニメデータ破棄
		for (i=0;i<ANN_ANM_NUM;i++){
			FLD_3DObjAnmDelete( &work->AnnAnm[j][i], &work->Allocator);
		}
		//モデルデータ破棄
		FLD_3DObjMdlDelete( &work->AnnMdl[j]);
	}
	//アニメデータ破棄
	for (i=0;i<EFF_ANM_NUM;i++){
		FLD_3DObjAnmDelete( &work->EffAnm[i], &work->Allocator);
	}
	//モデルデータ破棄
	FLD_3DObjMdlDelete( &work->EffMdl);
}


//==============================================================================
/**
 * アニメフレームセット
 *
 * @param	anm			アニメポインタ配列
 * @param	anm_num		アニメ数
 * @param	inFrame		フレーム
 *
 * @retval  none
 */
//==============================================================================
static void SetAnmFrame(FLD_3DOBJ_ANM *anm, const u8 anm_num, const u32 inFrame)
{
	u8 i;
	for (i=0;i<anm_num;i++){
		FLD_3DObjAnmSet( &anm[i], inFrame  );
	}
}

//==============================================================================
/**
 * アニメフレーム更新関数
 *
 * @param	anm			アニメポインタ配列
 * @param	anm_num		アニメ数
 *
 * @retval  BOOL		TRUE：アニメ終了	FALSE：アニメ継続
 */
//==============================================================================
static BOOL AnimeNoLoop(FLD_3DOBJ_ANM *anm, const u8 anm_num)
{
	u8 i;
	BOOL end;
	u8 end_num = 0;
	for (i=0;i<anm_num;i++){
		end = FLD_3DObjAnmNoLoop( &anm[i], FX32_ONE );
		if (end){
			OS_Printf("%d:アニメ終了\n",i);
			end_num++;
		}
	}
	if (end_num == anm_num){
		return TRUE;
	}

	return FALSE;
}

#if 0
#ifdef PM_DEBUG

//デバッグイベントセット関数
void DBG_FldAnnone_SetEvt(FIELDSYS_WORK * fsys)
{
	FLD_ANNONE_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(FLD_ANNONE_WORK));
	MI_CpuClear8(work, sizeof(FLD_ANNONE_WORK));
	work->fsys = fsys;
	//イベント発行
	FieldEvent_Set(fsys, FldAnnoneEvt, work);
}

void DBG_FldFlashBall_SetEvt(FIELDSYS_WORK * fsys, const u8 inType)
{
	FLD_FBALL_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(FLD_FBALL_WORK));
	MI_CpuClear8(work, sizeof(FLD_FBALL_WORK));
	work->fsys = fsys;
	work->Type = inType;
	//イベント発行
	FieldEvent_Set(fsys, FldFlashBallEvt, work);
}

#endif	//PM_DEBUG
#endif


//--------------------------------------------------------------------------------
//発光体関連


//--------------------------------------------------------------
/**
 * イベントコール関数
 * @param	event	イベントポインタ
 * @param	inType	0:ディアルガ 1:パルキア 2:ギラティナ
 * @return	none
 */
//--------------------------------------------------------------
void FldArceusEff_CallFlashBallEvt(FIELDSYS_WORK * fsys, const u8 inType)
{
	FLD_FBALL_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(FLD_FBALL_WORK));
	MI_CpuClear8(work, sizeof(FLD_FBALL_WORK));
	work->fsys = fsys;
	work->Type = inType;
	//イベント発行
	FieldEvent_Call(fsys->event, FldFlashBallEvt, work);
}

//--------------------------------------------------------------
/**
 * イベント関数
 * @param	event	イベントポインタ
 * @return	BOOL	TRUEで終了
 */
//--------------------------------------------------------------
static BOOL FldFlashBallEvt(GMEVENT_CONTROL * event)
{
	int *seq = FieldEvent_GetSeqWork(event);
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	FLD_FBALL_WORK* work = FieldEvent_GetSpecialWork(event);

	switch(*seq){
	case FB_SEQ_WHITE_OUT_FIRST:
		WIPE_SYS_Start(	WIPE_PATTERN_M, WIPE_TYPE_FADEOUT,
						WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE, FB_WHITE_OUT_FIRST_SYNC, 1, HEAPID_FIELD );
		(*seq)++;
		break;
	case FB_SEQ_EFF_LOAD:
		//ホワイトアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			//データロード
			LoadFb3DData(work);
			//ホワイトイン
			WIPE_SYS_Start(	WIPE_PATTERN_M, WIPE_TYPE_FADEIN,
						WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE, FB_WHITE_IN_SYNC, 1, HEAPID_FIELD );
			(*seq)++;
		}
		break;
	case FB_SEQ_WHITE_IN_WAIT:
		if( WIPE_SYS_EndCheck() ){
			//アニメ開始
			work->AnmStart = 1;
			work->AnmEnd = 0;
			(*seq)++;
		}
		break;
	case FB_SEQ_WAIT_ANM_END:		//発光体アニメ終了待ち
		if (work->AnmEnd){
			(*seq)++;
		}
		break;
	case FB_SEQ_END:	//解放処理
		DelFb3DData(work);
		sys_FreeMemoryEz(work);		//ワーク解放
		return TRUE;
	}

	//3Dアニメ
	if (work->AnmStart){
		work->AnmEnd = AnimeNoLoop(work->Anm, FBALL_ANM_NUM);
	}

	//3D描画
	if (work->DrawFlg){
		FLD_3DObjDraw( &work->Obj );
	}
	return FALSE;
}

//--------------------------------------------------------------
/**
 * 3Ｄデータロード関数
 * @param	work	ワークポインタ
 * @return	none
 */
//--------------------------------------------------------------
static void LoadFb3DData(FLD_FBALL_WORK *work)
{
	u8 i;

	int heap = HEAPID_FIELD;

	const int anm[3][FBALL_ANM_NUM] = {
		{
			NARC_fld_demo_sin_tama_nsbca,
			NARC_fld_demo_sin_tama_dl_nsbta,
			NARC_fld_demo_sin_tama_dl_nsbma,
			NARC_fld_demo_sin_tama_dl_nsbtp,
		},							//ディアルガ
		{
			NARC_fld_demo_sin_tama_nsbca,
			NARC_fld_demo_sin_tama_pl_nsbta,
			NARC_fld_demo_sin_tama_pl_nsbma,
			NARC_fld_demo_sin_tama_pl_nsbtp,
		},							//パルキア
		{
			NARC_fld_demo_sin_tama_nsbca,
			NARC_fld_demo_sin_tama_gr_nsbta,
			NARC_fld_demo_sin_tama_gr_nsbma,
			NARC_fld_demo_sin_tama_gr_nsbtp,
		},							//ギラティナ
	};

	const int mdl[3] = {
		NARC_fld_demo_sin_tama_dl_nsbmd,		//ディアルガ
		NARC_fld_demo_sin_tama_pl_nsbmd,		//パルキア
		NARC_fld_demo_sin_tama_gr_nsbmd,		//ギラティナ
	};

	// アロケーター作成
	sys_InitAllocator( &work->Allocator, heap, 32 );

	//モデルロード
	FLD_3DObjMdlLoad(&work->Mdl, ARC_FLD_DEMO_GRA , mdl[work->Type], heap);

	//アニメデータロード
	for (i=0;i<FBALL_ANM_NUM;i++){
		FLD_3DObjAnmLoad(	&work->Anm[i], &work->Mdl, ARC_FLD_DEMO_GRA, anm[work->Type][i],
								heap, &work->Allocator );
	}

	//描画オブジェクト初期化
	FLD_3DObjInit( &work->Obj, &work->Mdl );

	//アニメをリンク
	for (i=0;i<FBALL_ANM_NUM;i++){
		FLD_3DObjAddAnm( &work->Obj, &work->Anm[i] );
	}

	//描画フラグ設定	(表示)
	FLD_3DObjSetDraw( &work->Obj, TRUE );
	//フレームセット
	SetAnmFrame(work->Anm, FBALL_ANM_NUM, 0);

	//表示位置セット
	{
		VecFx32 vec;
		//連れ歩き（アルセウス）の位置に表示
		FieldOBJ_VecPosGet( PairPoke_GetFldObjPtr(work->fsys), &vec );
		FLD_3DObjSetMatrix( &work->Obj, vec.x, vec.y, vec.z );
	}

	//描画開始
	work->DrawFlg = 1;
}

//--------------------------------------------------------------
/**
 * 3Ｄデータ解放関数
 * @param	work	ワークポインタ
 * @return	none
 */
//--------------------------------------------------------------
static void DelFb3DData(FLD_FBALL_WORK *work)
{
	u8 i;
	for (i=0;i<FBALL_ANM_NUM;i++){
		//アニメデータ破棄
		FLD_3DObjAnmDelete( &work->Anm[i], &work->Allocator);
	}
	//モデルデータ破棄
	FLD_3DObjMdlDelete( &work->Mdl);
}
